
package com.shop.cloud.pay.admin.controller.ali;

import cn.hutool.core.util.StrUtil;
import com.alipay.easysdk.factory.MultipleFactory;
import com.alipay.easysdk.payment.app.models.AlipayTradeAppPayResponse;
import com.alipay.easysdk.payment.common.models.AlipayTradeFastpayRefundQueryResponse;
import com.alipay.easysdk.payment.common.models.AlipayTradeQueryResponse;
import com.alipay.easysdk.payment.common.models.AlipayTradeRefundResponse;
import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.alipay.easysdk.payment.wap.models.AlipayTradeWapPayResponse;
import com.alipay.easysdk.util.generic.models.AlipayOpenApiGenericResponse;
import com.shop.cloud.common.core.constant.CommonConstants;
import com.shop.cloud.common.core.util.R;
import com.shop.cloud.common.security.annotation.Inside;
import com.shop.cloud.pay.admin.config.AliPayConfiguration;
import com.shop.cloud.pay.admin.service.PayConfigService;
import com.shop.cloud.pay.common.constant.PayConstants;
import com.shop.cloud.pay.common.dto.AliBaseRequest;
import com.shop.cloud.pay.common.entity.PayConfig;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 支付宝支付
 *
 * @author
 * @date 2021-03-23 21:26:35
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/alipay")
@Tag(description = "alipay", name = "支付宝支付")
public class AliPayController {

	private final PayConfigService payConfigService;

	/**
	 * 调用统一下单接口（支付宝）
	 *
	 * @param aliBaseRequest 统一下单请求参数
	 * @return
	 */
	@Operation(summary = "调用统一下单接口（支付宝）")
	@Inside
	@PostMapping("/unifiedOrder")
	public R unifiedOrder(@RequestBody AliBaseRequest aliBaseRequest) throws Exception {
		log.debug("调用统一下单接口（支付宝）");
		Map<String,Object> params = aliBaseRequest.getParams();
		String tradeType = params.get("tradeType").toString();
		MultipleFactory multipleFactory = AliPayConfiguration.getFactory();
		PayConfig payConfig = payConfigService.findByType(PayConstants.PAY_TYPE_2);
		String appAuthToken = aliBaseRequest.getAppAuthToken();
		Map<String, Object> optionalArgs = new HashMap<>();
		if(PayConstants.PAY_MODEL_2.equals(payConfig.getModel())){//普通模式
			appAuthToken = null;
		}else{
			//服务商模式并已开户了分账，资金冻结开启分账
			if(CommonConstants.YES.equals(payConfig.getDividedEnable())){
				Map<String, Object> extendParams = new HashMap<>();
				extendParams.put("royalty_freeze","true");
				optionalArgs.put("extend_params",extendParams);
			}
		}
		if("NATIVE".equals(tradeType)){//电脑网页
			AlipayTradePagePayResponse alipayTradePagePayResponse = multipleFactory.Page()
					.agent(appAuthToken)
					.asyncNotify(params.get("notifyUrl").toString())
					.batchOptional(optionalArgs)
					.pay(params.get("subject").toString(),params.get("outTradeNo").toString(),params.get("totalAmount").toString(),params.get("returnUrl").toString());
			return R.ok(alipayTradePagePayResponse);
		}else if("APP".equals(tradeType)){//APP
			AlipayTradeAppPayResponse alipayTradeAppPayResponse = multipleFactory.App()
					.agent(appAuthToken)
					.asyncNotify(params.get("notifyUrl").toString())
					.batchOptional(optionalArgs)
					.pay(params.get("subject").toString(),params.get("outTradeNo").toString(),params.get("totalAmount").toString());
			return R.ok(alipayTradeAppPayResponse);
		}else if("MWEB".equals(tradeType)){//手机网站支付
			AlipayTradeWapPayResponse alipayTradeWapPayResponse = multipleFactory.Wap()
					.agent(appAuthToken)
					.asyncNotify(params.get("notifyUrl").toString())
					.batchOptional(optionalArgs)
					.pay(params.get("subject").toString(),params.get("outTradeNo").toString(),params.get("totalAmount").toString(),params.get("quitUrl").toString(),params.get("returnUrl").toString());
			return R.ok(alipayTradeWapPayResponse);
		}else if("QRCODE".equals(tradeType)){//扫码
			AlipayTradePrecreateResponse alipayTradePrecreateResponse = multipleFactory.FaceToFace()
					.agent(appAuthToken)
					.asyncNotify(params.get("notifyUrl").toString())
					.batchOptional(optionalArgs)
					.preCreate(params.get("subject").toString(), params.get("outTradeNo").toString(), params.get("totalAmount").toString());
			if(!PayConstants.ALI_RES_CODE_SUCCESS.equals(alipayTradePrecreateResponse.getCode())){
				log.error(StrUtil.format("{}:{}:{}:{}",
						alipayTradePrecreateResponse.getCode(),alipayTradePrecreateResponse.getMsg(),alipayTradePrecreateResponse.getSubCode(),alipayTradePrecreateResponse.getSubMsg()));
				return R.failed(alipayTradePrecreateResponse.getMsg()+":"+alipayTradePrecreateResponse.getSubMsg());
			}
			return R.ok(alipayTradePrecreateResponse);
		}else{
			return R.failed("该订单无支付类型");
		}
	}


	/**
	 * 查询订单（支付宝）
	 * @param aliBaseRequest
	 * @return
	 */
	@Operation(summary = "查询订单（支付宝）")
	@Inside
	@PostMapping("/queryOrder")
	public R queryOrder(@RequestBody AliBaseRequest aliBaseRequest) throws Exception {
		log.debug("查询订单（支付宝）");
		Map<String,Object> params = aliBaseRequest.getParams();
		MultipleFactory multipleFactory = AliPayConfiguration.getFactory();
		PayConfig payConfig = payConfigService.findByType(PayConstants.PAY_TYPE_2);
		String appAuthToken = aliBaseRequest.getAppAuthToken();
		if(PayConstants.PAY_MODEL_2.equals(payConfig.getModel())){//普通模式
			appAuthToken = null;
		}
		AlipayTradeQueryResponse alipayTradeQueryResponse = multipleFactory.Common().agent(appAuthToken).query(params.get("outTradeNo").toString());
		if(PayConstants.ALI_RES_CODE_SUCCESS.equals(alipayTradeQueryResponse.getCode())){
			return R.ok(alipayTradeQueryResponse);
		}else{
			return R.failed(alipayTradeQueryResponse,alipayTradeQueryResponse.getMsg()+"："+alipayTradeQueryResponse.getSubMsg());
		}
	}

	/**
	 * 申请退款（支付宝）
	 * @param aliBaseRequest
	 * @return
	 */
	@Operation(summary = "申请退款（支付宝）")
	@Inside
	@PostMapping("/refundOrder")
	public R refundOrder(@RequestBody AliBaseRequest aliBaseRequest) throws Exception {
		log.debug("申请退款（支付宝）");
		Map<String,Object> params = aliBaseRequest.getParams();
		MultipleFactory multipleFactory = AliPayConfiguration.getFactory();
		PayConfig payConfig = payConfigService.findByType(PayConstants.PAY_TYPE_2);
		String appAuthToken = aliBaseRequest.getAppAuthToken();
		if(PayConstants.PAY_MODEL_2.equals(payConfig.getModel())){//普通模式
			appAuthToken = null;
		}
		AlipayTradeRefundResponse alipayTradeRefundResponse = multipleFactory.Common().agent(appAuthToken)
				.optional("out_request_no",params.get("outRequestNo").toString())
				.refund(params.get("outTradeNo").toString(),params.get("refundAmount").toString());
		if(PayConstants.ALI_RES_CODE_SUCCESS.equals(alipayTradeRefundResponse.getCode())){
			return R.ok(alipayTradeRefundResponse);
		}else{
			return R.failed(alipayTradeRefundResponse,alipayTradeRefundResponse.getMsg()+"："+alipayTradeRefundResponse.getSubMsg());
		}
	}

	@Operation(summary = "查询退款（支付宝）")
	@Inside
	@PostMapping("/queryRefundOrder")
	public R queryRefundOrder(@RequestBody AliBaseRequest aliBaseRequest) throws Exception {
		log.debug("查询退款（支付宝）");
		Map<String,Object> params = aliBaseRequest.getParams();
		MultipleFactory multipleFactory = AliPayConfiguration.getFactory();
		PayConfig payConfig = payConfigService.findByType(PayConstants.PAY_TYPE_2);
		String appAuthToken = aliBaseRequest.getAppAuthToken();
		if(PayConstants.PAY_MODEL_2.equals(payConfig.getModel())){//普通模式
			appAuthToken = null;
		}
		AlipayTradeFastpayRefundQueryResponse alipayTradeFastpayRefundQueryResponse = multipleFactory.Common().agent(appAuthToken).queryRefund(params.get("outTradeNo").toString(),params.get("outRequestNo").toString());
		if(PayConstants.ALI_RES_CODE_SUCCESS.equals(alipayTradeFastpayRefundQueryResponse.getCode())){
			return R.ok(alipayTradeFastpayRefundQueryResponse);
		}else{
			return R.failed(alipayTradeFastpayRefundQueryResponse,alipayTradeFastpayRefundQueryResponse.getMsg()+"："+alipayTradeFastpayRefundQueryResponse.getSubMsg());
		}
	}

	@Operation(summary = "分账接口")
	@Inside
	@PostMapping("/profitsharing")
	public R profitSharingF(@RequestBody AliBaseRequest aliBaseRequest) {
		//分账
		AlipayOpenApiGenericResponse alipayOpenApiGenericResponse = this.profitSharing(aliBaseRequest);
		if(PayConstants.ALI_RES_CODE_SUCCESS.equals(alipayOpenApiGenericResponse.getCode())){
			return R.ok(alipayOpenApiGenericResponse);
		}else{
			//报关系未绑定错误，则调绑定方法
			if("ACQ.ROYALTY_RECEIVER_INVALID".equals(alipayOpenApiGenericResponse.getSubCode())){
				//获取分账时的接收方信息
				List<Map<String, Object>> royaltyParameters = (List) aliBaseRequest.getParams().get("royalty_parameters");
				List<Map<String, Object>> receiverList = new ArrayList<>();
				royaltyParameters.forEach(royaltyParameter ->{
					Map<String, Object> receiver = new HashMap<>();
					receiver.put("type",royaltyParameter.get("trans_in_type"));
					receiver.put("account",royaltyParameter.get("trans_in"));
					receiver.put("name",royaltyParameter.get("trans_in_name"));
					receiverList.add(receiver);
				});
				//分账关系绑定
				aliBaseRequest.getParams().put("receiver_list", receiverList);
				AlipayOpenApiGenericResponse alipayOpenApiGenericResponse2 = this.profitSharingRelationBind(aliBaseRequest);
				if(PayConstants.ALI_RES_CODE_SUCCESS.equals(alipayOpenApiGenericResponse2.getCode())){
					//关系绑定成功，则重新调用分账方法
					AlipayOpenApiGenericResponse alipayOpenApiGenericResponse3 = this.profitSharing(aliBaseRequest);
					if(PayConstants.ALI_RES_CODE_SUCCESS.equals(alipayOpenApiGenericResponse3.getCode())){
						return R.ok(alipayOpenApiGenericResponse3);
					}else{
						return R.failed(alipayOpenApiGenericResponse3,alipayOpenApiGenericResponse3.getMsg()+"："+alipayOpenApiGenericResponse3.getSubMsg());
					}
				}else{
					return R.failed(alipayOpenApiGenericResponse2,alipayOpenApiGenericResponse2.getMsg()+"："+alipayOpenApiGenericResponse2.getSubMsg());
				}
			}else{
				return R.failed(alipayOpenApiGenericResponse,alipayOpenApiGenericResponse.getMsg()+"："+alipayOpenApiGenericResponse.getSubMsg());
			}
		}
	}

	/**
	 * 分账接口
	 * @param aliBaseRequest
	 * @return
	 */
	@SneakyThrows
	private AlipayOpenApiGenericResponse profitSharing(AliBaseRequest aliBaseRequest){
		log.debug("分账接口（支付宝）");
		MultipleFactory multipleFactory = AliPayConfiguration.getFactory();
		PayConfig payConfig = payConfigService.findByType(PayConstants.PAY_TYPE_2);
		String appAuthToken = aliBaseRequest.getAppAuthToken();
		if(PayConstants.PAY_MODEL_2.equals(payConfig.getModel())){//普通模式
			appAuthToken = null;
		}
		Map<String, String> textParams = new HashMap<>();
		Map<String, ?> bizParams = aliBaseRequest.getParams();
		return multipleFactory.Generic().agent(appAuthToken).execute("alipay.trade.order.settle", textParams, bizParams);
	}

	/**
	 * 分账关系绑定
	 * @param aliBaseRequest
	 * @return
	 */
	@SneakyThrows
	private AlipayOpenApiGenericResponse profitSharingRelationBind(AliBaseRequest aliBaseRequest){
		log.debug("分账关系绑定）");
		MultipleFactory multipleFactory = AliPayConfiguration.getFactory();
		PayConfig payConfig = payConfigService.findByType(PayConstants.PAY_TYPE_2);
		String appAuthToken = aliBaseRequest.getAppAuthToken();
		if(PayConstants.PAY_MODEL_2.equals(payConfig.getModel())){//普通模式
			appAuthToken = null;
		}
		Map<String, String> textParams = new HashMap<>();
		Map<String, ?> bizParams = aliBaseRequest.getParams();
		AlipayOpenApiGenericResponse alipayOpenApiGenericResponse = multipleFactory.Generic().agent(appAuthToken).execute("alipay.trade.royalty.relation.bind", textParams, bizParams);
		return alipayOpenApiGenericResponse;
	}
}
